﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Net.Sockets;
using ScreenMonitor.Common.Objects;
using System.ComponentModel;
using ScreenMonitor.Common;
using ScreenMonitor.Common.File;
using System.Windows.Forms;

namespace ScreenMonitor.ServerLib
{
    /// <summary>
    /// 为客户端状态提供枚举
    /// </summary>
    public enum ClientState
    {
        Init,
        Connected,
        DisConnected,
    }

    /// <summary>
    /// 为签到状态提供枚举
    /// </summary>
    public enum SignState
    {
        Signing,
        Signed,
        UnSigned,
        NeverSigned
    }
    
    /// <summary>
    /// 客户端对象封装
    /// </summary>
    public class ClientObject
    {

        #region==========属性==========

        private Image ScreenImageV;
        /// <summary>
        /// 获取或设置客户端发送过来的桌面图像
        /// </summary>
        [ReadOnly(true)]
        [DisplayName("桌面图像")]
        [Description("表示客户端发送过来的桌面图像信息")]
        public Image ScreenImage
        {
            get { return ScreenImageV; }
            set
            {
                ScreenImageV = value;
                if (ImageChanged != null)
                    ImageChanged(this, new EventArgs());
            }
        }

        private string InfoStrV;
        /// <summary>
        /// 获取或设置客户端的信息字段
        /// </summary>
        [DisplayName("显示名")]
        [Description("表示客户端在服务端的显示名称")]
        public string InfoStr
        {
            get { return InfoStrV; }
            set 
            { 
                InfoStrV = value;
                if (InfoStrChanged != null)
                    InfoStrChanged(this, new EventArgs());
            }
        }

        private ClientState StateV;
        /// <summary>
        /// 获取客户端目前的状态
        /// </summary>
        [DisplayName("连接状态")]
        [Description("表示客户端的当前连接状态")]
        public ClientState State
        {
            get { return StateV; }
            internal set 
            { 
                StateV = value;
                if (StateChanged != null)
                    StateChanged(this, new EventArgs());
            }
        }

        private SignState SignStateV=SignState.NeverSigned;
        /// <summary>
        /// 获取或设置客户端目前的签到状态
        /// </summary>
        [DisplayName("签到状态")]
        [Description("表示客户端的签到状态")]
        public SignState SignState
        {
            get { return SignStateV; }
            set 
            { 
                SignStateV = value;
                if (SignStateChanged != null)
                    SignStateChanged(this, new EventArgs());
            }
        }
        private SignResponceObject StudentInfoV;

        /// <summary>
        /// 获取或设置客户端关联的学生信息实例
        /// </summary>
        [DisplayName("学生信息")]
        [Description("表示客户端关联的学生信息实例")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public SignResponceObject StudentInfo
        {
            get { return StudentInfoV; }
            set 
            { 
                StudentInfoV = value;
                if (StudentInfoChanged != null)
                    StudentInfoChanged(this, new EventArgs());
            }
        }
        
        /// <summary>
        /// 获取该实例关联的基础客户端连接
        /// </summary>
        [ReadOnly(true)]
        [DisplayName("基础连接")]
        [Description("表示该客户端的基础连接")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public TcpClient Client { get; private set; }

        /// <summary>
        /// 获取该客户端的信息存储
        /// </summary>
        [ReadOnly(true)]
        [DisplayName("信息")]
        [Description("表示该客户端的连接信息")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public ClientInfo Info { get; private set; }

        private bool IsPauseSendImgV=!ServerGlobalSettingScreenViewImg.AutoStartSendBmp;
        /// <summary>
        /// 表示客户端是否应该暂停发送图片
        /// </summary>
        [ReadOnly(false)]
        [DisplayName("暂停发送图片")]
        [Description("表示该客户端是否应该暂停发送图片")]
        public bool IsPausedSendImg
        {
            get{return IsPauseSendImgV;}
            set 
            {
                if (!IsPauseSendImgV == value)
                {
                    IsPauseSendImgV = value;

                    string command;
                    if (value)
                        command = CommandType.PauseSendBitMap;
                    else
                        command = CommandType.StartSendBitMap;
                    CommandObjects.TcpCommandCenter.SendCommand(command, Client);

                    if (IsPausedSendImgChanged != null)
                        IsPausedSendImgChanged(this, new EventArgs());
                }
            }
        }

        private Size SendImgSizeV=new Size(
            ServerGlobalSettingScreenViewImg.ScreenImgWidth,
            ServerGlobalSettingScreenViewImg.ScreenImgHeight);
        /// <summary>
        /// 表示客户端发送的屏幕截图的大小
        /// </summary>
        [ReadOnly(false)]
        [DisplayName("截图大小")]
        [Description("表示该客户端发送的截图的大小")]
        public Size SendImgSize
        {
            get 
            { return SendImgSizeV; }
            set 
            {
                if (value != SendImgSizeV)
                {
                    SendImgSizeV = value;
                    CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SetBitMapSize, Util.SizeToByte(value), Client);
                    if(SendImgSizeChanged!=null)
                    {
                        SendImgSizeChanged(this, new EventArgs());
                    }
                }
            }
        }

        private PictureBoxSizeMode SendImgSizeModeV = ServerGlobalSettingScreenViewImg.ImageSizeMode;
        /// <summary>
        /// 表示客户端发送屏幕截图的缩放模式
        /// </summary>
        [ReadOnly(false)]
        [DisplayName("缩放模式")]
        [Description("表示该客户端发送的截图的缩放模式")]
        public PictureBoxSizeMode SendImgSizeMode
        {
            get { return SendImgSizeModeV; }
            set 
            {
                if (value != SendImgSizeModeV)
                {
                    SendImgSizeModeV = value;
                    CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SetBitMapSizeMode, BitConverter.GetBytes((int)value), Client);
                    if (SendImgSizeModeChanged != null)
                    {
                        SendImgSizeModeChanged(this, EventArgs.Empty);
                    }
                }
            }
        }
        
        private string SendImgFormatV=ServerGlobalSettingScreenViewImg.ImageType;
        /// <summary>
        /// 表示客户端发送的屏幕截图的格式
        /// </summary>
        [ReadOnly(false)]
        [DisplayName("截图格式")]
        [Description("表示该客户端发送的截图格式/n支持以下值：Bmp,Gif,Jpeg,Png")]
        public string SendImgFormat
        {
            get { return SendImgFormatV; }
            set 
            {
                if (value != SendImgFormatV)
                {
                    SendImgFormatV = value;
                    CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SetBitMapFormat, Encoding.UTF8.GetBytes(value), Client);
                    if (SendImgFormatChanged != null)
                        SendImgFormatChanged(this, new EventArgs());
                }
            }
        }

        private int SendImgRateV = ServerGlobalSettingScreenViewImg.SendBmpRate;
        /// <summary>
        /// 表示客户端发送屏幕截图的频率
        /// </summary>
        [ReadOnly(false)]
        [DisplayName("截图频率")]
        [Description("表示客户端发送屏幕截图的频率")]
        public int SendImgRate
        {
            get { return SendImgRateV; }
            set 
            {
                if (SendImgRateV != value)
                {
                    SendImgRateV = value;
                    CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SetBitMapFormat, BitConverter.GetBytes(value), Client);
                    if (SendImgRateChanged != null)
                        SendImgRateChanged(this, new EventArgs());
                }
            }
        }
        
        #endregion

        #region==========事件==========

        public event EventHandler ImageChanged;
        public event EventHandler InfoStrChanged;
        public event EventHandler StateChanged;
        public event EventHandler SignStateChanged;
        public event EventHandler StudentInfoChanged;
        public event EventHandler IsPausedSendImgChanged;
        public event EventHandler SendImgSizeChanged;
        public event EventHandler SendImgFormatChanged;
        public event EventHandler SendImgRateChanged;
        public event EventHandler SendImgSizeModeChanged;

        #endregion

        #region========构造函数========

        /// <summary>
        /// 通过指定的基础连接构造客户端新实例
        /// </summary>
        /// <param name="Client"></param>
        public ClientObject(TcpClient Client)
        {
            this.Client = Client;
            this.Info = new ClientInfo();
        }

        #endregion

        #region========命令相关========

        /// <summary>
        /// 向客户端发送消息
        /// </summary>
        /// <param name="HeadText"></param>
        public void SendMsg(string HeadText,string Msg)
        {
            SendMessageObject obj = new SendMessageObject();
            obj.Title = HeadText;
            obj.Message = Msg;
            CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SendMessage, obj.ToByte(),Client);
        }

        /// <summary>
        /// 向客户端传送文件
        /// </summary>
        /// <param name="FilePath">文件路径</param>
        /// <param name="Tag">发送包含的用户信息(不会发送，会加入到返回的文件请求对象中)</param>
        /// <returns>发送文件的请求实例</returns>
        public FileRequestObject StartSendFile(string FilePath,object Tag=null)
        {
            FileRequestObject obj = FilePool.BeginSendFile(FilePath, Tag);
            CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.WantToSendFile, obj.ToByte(),Client);
            return obj;
        }

        /// <summary>
        /// 提示客户端开始远程控制
        /// </summary>
        public void StartControl()
        {
            CommandObjects.TcpCommandCenter.SendCommand(CommandType.StartControl, Client);
        }

        /// <summary>
        /// 提示客户端停止远程控制
        /// </summary>
        public void StopControl()
        {
            CommandObjects.TcpCommandCenter.SendCommand(CommandType.StopControl, Client);
        }

        /// <summary>
        /// 令客户端执行指定鼠标事件
        /// </summary>
        /// <param name="EveType">鼠标事件类型</param>
        /// <param name="MousePoint">鼠标坐标</param>
        public void DoMouseEvent(MouseEventType EveType,Point MousePoint)
        {
            MouseEventObject MouseObj = new MouseEventObject();
            MouseObj.Type = EveType;
            MouseObj.X = MousePoint.X;
            MouseObj.Y = MousePoint.Y;
            CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.DoMouseEvent, MouseObj.ToByte(), Client);
        }

        /// <summary>
        /// 令客户端执行指定键盘事件
        /// </summary>
        /// <param name="EveType">键盘事件类型</param>
        /// <param name="KeyCode">键盘按键</param>
        public void DoKeyboardEvent(KeyBoardType EveType,Keys KeyCode)
        {
            KeyBoardEventObject obj = new KeyBoardEventObject();
            obj.KeyCode = KeyCode;
            obj.Type = EveType;
            CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.DoKeyBoardEvent, obj.ToByte(), Client);
        }

        /// <summary>
        /// 令客户端立即发送一个屏幕截图到服务端
        /// </summary>
        public void RefreshBitMap()
        {
            CommandObjects.TcpCommandCenter.SendCommand(CommandType.SendBitMap, Client);
        }

        /// <summary>
        /// 向客户端发送Ping请求
        /// </summary>
        public void Ping()
        {
            CommandObjects.TcpCommandCenter.SendCommand(CommandType.Ping, Client);
        }

        #endregion
    }

}
